import math
from ._global import PRECISION


class Vector:
    def __init__(self, ls):
        """不希望构造函数传进来的向量不被更改 复制list使用"""
        self._values = list(ls)

    @classmethod
    def zero(cls, dimensionality):
        """创建指定维度 0 向量"""
        return Vector([0] * dimensionality)

    def norm(self):
        """向量取模 即求向量的长度 向量中很重要"""
        return math.sqrt(sum(e**2 for e in self))

    def normalize(self):
        """向量求方向 也就是求单位向量 它的模一定是1 验证单位向量 看模是否为 1 向量中很重要"""
        # return 1 / self.norm * (for e in self)
        # return 1 / self.norm * self._values
        if self.norm() < PRECISION:
            raise ZeroDivisionError("zero is error")
        return 1 / self.norm() * Vector(self.__iter__())

    def dot(self,other):
        """向量点成 x1 • y1 + x2 • y2"""
        return sum(a * b for a, b in zip(self,other))

    def __add__(self, other):
        """使用迭代器返回对象对应的迭代器。不希望更改 values"""
        assert len(self) == len(other),\
            "length must be same"
        return Vector([a+b for a, b in zip(self,other)])

    def __sub__(self, other):
        """使用迭代器返回对象对应的迭代器。不希望更改 values"""
        assert len(self) == len(other), \
            "length must be same"
        return Vector([a - b for a, b in zip(self, other)])

    def __mul__(self, n):
        """向量乘法 self * n"""
        return Vector([n * e for e in self])

    def __rmul__(self, n):
        """向量颠倒容错性 上面是 向量 * 数 / 这里是 数 * 向量"""
        return self * n

    def __pos__(self):
        """向量取正"""
        return 1 * self

    def __neg__(self):
        """向量取负"""
        return -1 * self

    def __iter__(self):
        return self._values.__iter__()

    def __getitem__(self, item):
        """获取向量元素"""
        return self._values[item]

    def __len__(self):
        """返回向量长度"""
        return len(self._values)

    def __repr__(self):
        return "vector({})".format(self._values)

    def __str__(self):
        return "({})".format(" , ".join(str(e) for e in self._values))